package org.ysh.listener;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import org.ysh.core.annotation.ResourceEx;
import org.ysh.domain.Resource;
import org.ysh.service.ResourceService;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 资源注册监听器类
 */
@Component
@Slf4j
public class ResourceRegisterListener implements ApplicationListener<ContextRefreshedEvent> {

    @javax.annotation.Resource
    ResourceService resourceService;
    @Override
    public void onApplicationEvent(ContextRefreshedEvent applicationEvent) {
        log.error("系统事件 ===> {}",applicationEvent );
        ApplicationContext context = applicationEvent.getApplicationContext();

        RequestMappingHandlerMapping mapping = context.getBean(RequestMappingHandlerMapping.class);
        Map<RequestMappingInfo, HandlerMethod> handlerMethods = mapping.getHandlerMethods();
        Set<Class<?>> controllers = handlerMethods.values().stream().map(HandlerMethod::getBeanType).collect(Collectors.toSet());

        List<Resource> resources = findResources(controllers);
        this.resourceService.save(resources);
    }

    // 查找资源方法
    private List<Resource> findResources(Set<Class<?>> controllers){
        List<Resource> resources = new ArrayList<>();

        for(Class<?> controller : controllers){
            String path = "";
            path = getPath(controller, path);


//            // 获取类上的菜单信息，默认是顶级菜单
//            ResourceEx resourceEx = controller.getAnnotation(ResourceEx.class);
//            if(resourceEx != null) {
//                //封装资源信息
//                Resource resource = new Resource(resourceEx);
//                resource.setUrl(path);
//                resources.add(resource);
//            }

            //查找方法上的菜单信息
            Method[] methods = controller.getMethods();
            for (Method method : methods) {
                ResourceEx res = method.getAnnotation(ResourceEx.class);
                if (res != null) {

                    Resource resource = getResource(method, res, path);
                    resources.add(resource);
                }
            }
        }
        return resources;
    }

    /**
     * 获取Controller上的路径
     * @param controller
     * @param path
     * @return
     */
    private static String getPath(Class<?> controller, String path) {
        RequestMapping requestMapping = controller.getAnnotation(RequestMapping.class);
        if(requestMapping!= null){
            String[] values = requestMapping.value();
            if(!ObjectUtils.isEmpty(values)){
                path = values[0];
            }
        }else {
            GetMapping getMapping = controller.getAnnotation(GetMapping.class);
            if(getMapping != null){
                String[] values = getMapping.value();
                if(!ObjectUtils.isEmpty(values)){
                    path = values[0];
                }
            }else{
                PostMapping postMapping = controller.getAnnotation(PostMapping.class);
                if(postMapping != null){
                    String[] values = postMapping.value();
                    if(!ObjectUtils.isEmpty(values)){
                        path = values[0];
                    }
                }
            }
        }
        return path;
    }

    /**
     * 获取方法上的路径，并封装为resource对象
     * @param method
     * @param res
     * @param path
     * @return
     */
    private static Resource getResource(Method method, ResourceEx res, String path) {
        RequestMapping mapping = method.getAnnotation(RequestMapping.class);
        String url = "";
        if (mapping != null && mapping.value().length > 0) {
            url = mapping.value()[0];
        }else{
            GetMapping getMapping = method.getAnnotation(GetMapping.class);
            if (getMapping != null && getMapping.value().length > 0) {
                url = getMapping.value()[0];
            }else{
                PostMapping postMapping = method.getAnnotation(PostMapping.class);
                if (postMapping != null && postMapping.value().length > 0) {
                    url = postMapping.value()[0];
                }
            }
        }
        //封装资源信息
        Resource resource = new Resource(res);
        resource.setUrl(path + url);
        return resource;
    }
}
